import os
import smtplib
import traceback
import secrets
from email.mime.text import MIMEText
from email.utils import formataddr
from dotenv import load_dotenv
from extensions.redis_ext import redis_store

# 读取环境变量
load_dotenv()

# 获取环境变量
EMAIL_SMTP_SERVER = os.getenv("EMAIL_SMTP_SERVER")
EMAIL_SMTP_PORT = os.getenv("EMAIL_SMTP_PORT")
EMAIL_SENDER = os.getenv("EMAIL_SENDER")
EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD")

CODE_EXPIRE_TIME = 300  # 验证码有效期，单位为秒

def _generate_email_body(code: str) -> str:
    """生成邮件内容

    Parameters:
        code: 验证码

    Returns:
        包含验证码的邮件内容
    """
    return f"""
    <html>
    <head>
      <style>
        body {{
          color: #333;
        }}
        .body {{
          box-sizing: border-box;
          width: 100%;
          max-width: 600px;
          margin: auto;
          padding: 20px;
          background-color: #f9f9f9;
          border-radius: 5px;
          box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }}
        .header {{
          color: #0066cc;
          font-size: 24px;
          font-weight: bold;
          margin-bottom: 20px;
          border-bottom: 2px solid #0066cc;
        }}
        .start {{
          font-size: 18px;
          font-weight: bold;
          color: #333;
          margin-bottom: 10px;
        }}
        .str {{
          color: #0066cc;
        }}
        .code {{
          font-size: 26px;
          font-weight: bolder;
          color: #19436d;
          background-color: #e9e9e9;
          border-radius: 5px;
          text-align: center;
          margin: 15px 0;
          padding: 10px 20px;
        }}
        .footer {{
          font-size: 12px;
          color: #666;
          border-top: 1px solid #eee;
          margin-top: 20px;
          padding-top: 10px;
        }}
      </style>
    </head>
    <body>
      <div class="body">
        <header class="header">今日事一站知</header>
        <div class="start">尊敬的用户：您好！</div>
        <div>
          您正在进行<strong class="str">注册账号</strong>操作，以下是您的验证码：
        </div>
        <div class="code">
          {code}
        </div>
        <div>
          该验证码有效期为<strong class="str">5分钟</strong>，请尽快完成注册操作，若您未进行注册操作，请忽略此邮件。
        </div>
        <div class="footer">
          此邮件由系统自动发送，请勿回复或转发。<br />
          © 2025 今日事一站知
        </div>
      </div>
    </body>
    </html>
    """

def send_code_email(code, user_email) -> None:
    """发送验证码邮件

    Parameters:
        code: 验证码
        user_email: 用户邮箱
    
    """
    try:
        msg = MIMEText(_generate_email_body(code), "html", "utf-8")  # 填写邮件内容
        msg["From"] = formataddr(
            ["今日事一站知", EMAIL_SENDER]
        )  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
        msg["To"] = user_email  # 收件人邮箱账号
        msg["Subject"] = "今日事一站知"  # 邮件的主题，也可以说是标题

        server = smtplib.SMTP_SSL("smtp.qq.com", 465)  # 发件人邮箱中的SMTP服务器
        server.login(EMAIL_SENDER, EMAIL_PASSWORD)  # 括号中对应的是发件人邮箱账号、邮箱授权码
        server.sendmail(
            EMAIL_SENDER,
            [
                user_email,
            ],
            msg.as_string(),
        )  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
        server.quit()  # 关闭连接
    except Exception as e:
        print("邮件发送失败:", e)
        print("详细错误信息:")
        traceback.print_exc()
        raise

def generate_code(email:str, length:int=4) -> str:
    """生成指定长度的随机数字验证码，并将其存储在redis中
    
    Parameters:
        email: 用户邮箱
        length: 验证码长度，默认为4位
        
    Returns:
        str: 生成的数字验证码
    """
    code = ''.join(secrets.choice('0123456789') for _ in range(length))
    redis_client = redis_store.redis_client
    if redis_client is None:
        raise ValueError("Redis 尚未初始化")
    redis_client.set(email, code, ex=CODE_EXPIRE_TIME)
    return code

def verify_code(email:str, code:str) -> bool:
    """验证验证码是否正确
    
    Parameters:
        email: 用户邮箱
        code: 用户输入的验证码
        
    Returns:
        bool: 验证码是否正确
    """
    redis_client = redis_store.redis_client
    if redis_client is None:
        raise ValueError("Redis 尚未初始化")
    stored_code = redis_client.get(email)
    if stored_code and stored_code == code:
        redis_client.delete(email)
        return True
    return False
